/*
 * T.Raynal - A.Aviles - F.Diallo
 * XML-Scenarios
 * PPA AL5-2
 * December 2012 
 */


import java.io.File;
import java.io.IOException;
import java.util.Scanner;
import java.util.concurrent.atomic.AtomicReference;

import org.jdom2.JDOMException;

import output.IOutputter;
import output.ftp.OutputterFTP;
import model.*;
import model.scenario.XmlParsingException;
import common.Commons;
import common.Context;
import common.exception.*;
import facade.ScenarioManager;

//Set de scenarios
//gestionnaire xsl

public class Shell {

	//
	private static boolean DEBUG = false;
	//
	
	private static Scanner in = null;
	private static ScenarioManager manager = null;
	private static  String COMMAND;
	private static String ARG;
	private static Scenario CURRENT_SCENARIO;
	
	private static final String EXIT = "exit";
	private static final String SAVE = "save";
	private static final String LOAD = "load";
	private static final String RUN = "run";
	private static final String ABORT = "abort";
	private static final String BROWNSE_SCENARIOS = "scenario?";
	private static final String BROWNSE_SAVES = "saves?";
	private static final String SYNCHRONIZE = "sync";
	
	private static void exit()
	{
		System.out.println("Exit shell?");
		if (in.nextLine().equals("y"))
		{
			System.out.println("Bye");
			in.close();
			System.exit(0);	
		}
	}
	
	public static void save(Scenario scenario)
	{
		String name =Context.REPOSITORY_SAVES +
								File.separator +
									scenario.id() 
										+ "_" + 
											System.currentTimeMillis();
		
		try {
			scenario.save(name);
			
		System.out.println("Scenario saved :" + name);
		
		} catch (IOException e) {
			System.out.println("An error has occured while saving the scenario:\n"+ e.getMessage());
		}
	}
	
	private static void printScenario()
	{
		System.out.println("Available scenarios: ");
		int i =1;
		for (Scenario scenario : manager.scenarios()) {
			System.out.println(i + " " + scenario.id());
			i++;	
		}
	}
	
	private static void run()
	{
		
		String input;
		Situation current_situation = null;
		Case current_case;
		Expression current_expression;
		
		try {
			
			while (null !=(current_situation  = CURRENT_SCENARIO.next()))
			{
				
				if (current_situation.isBottleneck())
				{
					System.out.println("You must at least validate a case. Situation will reload.");
					current_situation.reset();
				}
				
				System.out.println("You've reached sitaution "+ current_situation.id());
				
				//REFACTOR//
				if (DEBUG)
					current_situation.reset();
				////////////
				
				while (null !=(current_case = current_situation.next()))
				{
					System.out.println("Firing case " + current_case.id() + "!");
					
					while (null !=(current_expression= current_case.next()))
					{
						boolean b = true;
						
						while (b)
						{
							
							System.out.println("Eval that! " + current_expression.id());
							input = in.nextLine();
							
							if (input.equals(SAVE))
							{
								save(CURRENT_SCENARIO);
							}
							
							else if (input.equals(EXIT))
							{
								exit();
							}
							
							else if (input.equals(ABORT))
							{
								return;
							}
							else
							{
								try 
								{
									current_expression.setEvaluatee(input);
									b = false;
								}
								catch (EvaluationException e)
								{
									System.out.println(e.getMessage());
								}	
							}
						}
					}
					
					if (current_situation.eval())
					{
						break;
					}
				}
			}
		} catch (EvaluationException e) {
			e.printStackTrace();
			CURRENT_SCENARIO.reset();
		}
		
		System.out.println("Scenario completed!");
		
		CURRENT_SCENARIO.reset();
		
	}
	
	private static void handleInput ()
	{
		String input = in.nextLine();
		
		COMMAND= input;
		
		String [] values  = input.split(" ");	
		
		if(values.length>1)
		{
			COMMAND = values[0];	
			ARG= values[1];
		}
	}
	
	
	public static void main(String[] args) {
		
		
		in = new Scanner(System.in);
			
			try {
				manager = new ScenarioManager();
			} catch (InitialisationException e) {
				System.out.println(e.getMessage());
				in.close();
				return;
			}
			
			try {
				manager.load();
			} catch (UnregisteredOperatorException | JDOMException
					| IOException | XmlParsingException e) {
				System.out.println(e.toString());
				in.close();
				return;
			}

		while (true)
		{
			System.out.println("Enter a command : ");
			
			handleInput();

			switch (COMMAND)
			{
			
			case BROWNSE_SCENARIOS:
				printScenario();
				break;
				
			case SYNCHRONIZE:
				
				System.out.println("Synchronizing...");
				IOutputter synch = new OutputterFTP();
				synch.initialize();
				AtomicReference<String> _log = new AtomicReference<>();
				synch.synchronize(_log);
				synch.dispose();
				System.out.println(_log);
				break;
				
			case RUN:
				
				if (Commons.isNumeric(ARG) && 
						(Integer.valueOf(ARG)-1)>-1 && (Integer.valueOf(ARG)-1)<manager.scenarios().size())
				{	
					CURRENT_SCENARIO  = manager.scenarios().get(Integer.valueOf(ARG)-1);
					
					CURRENT_SCENARIO.reset();
					run();
				}
				
				break;
			case BROWNSE_SAVES:
				int i =1;
				for (String save : manager.saves()) {
					System.out.println(i + " " + save);
					i++;
				}
			break;
			
			case LOAD:
				
				if (Commons.isNumeric(ARG) && 
						(Integer.valueOf(ARG)-1)>-1 && (Integer.valueOf(ARG)-1)<manager.saves().size())
				{	
					try {
						CURRENT_SCENARIO = manager.loadSave(manager.saves().get(Integer.valueOf(ARG)-1));
					} catch (NumberFormatException | ClassNotFoundException
							| IOException e) {
						System.out.println("An error has occured while loading the save :\n" + e.getMessage());
					}
					
					if (null!= CURRENT_SCENARIO)
							run();
				
				}
				break;
			case EXIT:
				exit();
				return;
				
			default:
				System.out.println("Unrecognized command");
				break;
			
			}
		}
	}

}
